﻿using System.Diagnostics;

/// <summary>
/// ILMerge合并DLL的帮助类
/// </summary>
public static class ILMergeHelper
{
    /// <summary>
    /// 执行ILMerge合并DLL
    /// </summary>
    /// <param name="ilmergePath">ILMerge的路径</param>
    /// <param name="outputDllPath">输出DLL的路径</param>
    /// <param name="dllsToMerge">要合并的DLLs路径</param>
    /// <param name="additionalOptions">额外的ILMerge选项</param>
    /// <param name="timeoutMs">超时时间(毫秒)，默认5分钟</param>
    /// <returns>合并结果对象</returns>
    public static MergeResult MergeDll(
        string ilmergePath,
        string outputDllPath,
        string[] dllsToMerge,
        string[] additionalOptions = null,
        int timeoutMs = 300000)
    {
        if (string.IsNullOrWhiteSpace(ilmergePath))
            throw new ArgumentNullException(nameof(ilmergePath));
        if (string.IsNullOrWhiteSpace(outputDllPath))
            throw new ArgumentNullException(nameof(outputDllPath));
        if (dllsToMerge == null || dllsToMerge.Length == 0)
            throw new ArgumentException("至少需要指定一个要合并的DLL", nameof(dllsToMerge));
        // 检查文件是否存在
        if (!File.Exists(ilmergePath))
            return MergeResult.Fail($"ILMerge工具不存在: {ilmergePath}");
        var missingDlls = dllsToMerge.Where(dll => !File.Exists(dll)).ToList();
        if (missingDlls.Count != 0)
            return MergeResult.Fail($"找不到要合并的DLL文件: {string.Join(", ", missingDlls)}");
        // 确保输出目录存在
        string? outputDir = Path.GetDirectoryName(outputDllPath);
        if (!string.IsNullOrWhiteSpace(outputDir) && !Directory.Exists(outputDir))
        {
            try
            {
                Directory.CreateDirectory(outputDir);
            }
            catch (Exception ex)
            {
                return MergeResult.Fail($"无法创建输出目录: {outputDir}. 错误: {ex.Message}");
            }
        }

        // 构建ILMerge的命令行参数
        var arguments = new System.Text.StringBuilder();
        arguments.Append("/ndebug /target:dll ");
        
        // 添加额外选项
        if (additionalOptions != null)
        {
            foreach (var option in additionalOptions)
            {
                arguments.Append($"{option} ");
            }
        }
        
        arguments.Append($"/out:\"{outputDllPath}\" ");
        arguments.Append(string.Join(" ", dllsToMerge.Select(dll => $"\"{dll}\"")));

        // 创建新的进程启动信息
        var startInfo = new ProcessStartInfo
        {
            FileName = ilmergePath,
            Arguments = arguments.ToString(),
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true,
            WorkingDirectory = Path.GetDirectoryName(ilmergePath) ?? Environment.CurrentDirectory
        };

        try
        {
            using var process = new Process { StartInfo = startInfo };
            // 启动ILMerge进程
            if (!process.Start())
                return MergeResult.Fail("无法启动ILMerge进程");
            // 异步读取输出和错误信息
            var outputTask = process.StandardOutput.ReadToEndAsync();
            var errorTask = process.StandardError.ReadToEndAsync();

            // 等待进程完成或超时
            if (!process.WaitForExit(timeoutMs))
            {
                try { process.Kill(); } catch { /* 忽略杀死进程时的异常 */ }
                return MergeResult.Fail($"ILMerge操作超时(超过 {timeoutMs}ms)");
            }

            // 确保读取完成
            Task.WaitAll(outputTask, errorTask);
            string output = outputTask.Result;
            string error = errorTask.Result;

            // 检查进程退出代码以确定是否成功
            if (process.ExitCode == 0)
            {
                return File.Exists(outputDllPath) 
                    ? MergeResult.Success2(output, error) 
                    : MergeResult.Fail("ILMerge报告成功但未生成输出文件", output, error);
            }
            
            return MergeResult.Fail($"ILMerge失败，退出代码: {process.ExitCode}", output, error);
        }
        catch (Exception ex)
        {
            return MergeResult.Fail($"执行ILMerge时发生异常: {ex.Message}");
        }
    }
}

/// <summary>
/// ILMerge操作结果
/// </summary>
public class MergeResult
{
    public bool Success { get; }
    public string Output { get; }
    public string Error { get; }
    public string Message { get; }

    private MergeResult(bool success, string message, string output, string error)
    {
        Success = success;
        Message = message;
        Output = output;
        Error = error;
    }
    public static MergeResult Success2(string output, string error) 
        => new MergeResult(true, "合并成功", output, error);
    public static MergeResult Fail(string message, string output = null, string error = null) 
        => new MergeResult(false, message, output, error);
}
